package com.xusiyan08.service;

import com.xusiyan08.dto.MessageDto;
import com.xusiyan08.entity.Item;
import com.xusiyan08.entity.Message;
import com.xusiyan08.entity.User;
import com.xusiyan08.repository.MessageRepository;
import com.xusiyan08.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class MessageService {

    private static final Logger logger = LoggerFactory.getLogger(MessageService.class);

    @Autowired
    private MessageRepository messageRepository;
    @Autowired // 注入 UserRepository 或 UserService
    private UserRepository userRepository; // 或者 UserService userService;
    @Autowired
    private ItemService itemService; // Inject ItemService


    public List<User> getConversationsUsers(Long currentUserId) {
        // 获取所有给当前用户发送过消息的用户ID
        Set<Long> senderIds = messageRepository.findDistinctSenderIdsByReceiverId(currentUserId);
        // 获取所有当前用户发送过消息的用户ID
        Set<Long> receiverIds = messageRepository.findDistinctReceiverIdsBySenderId(currentUserId);

        // 合并两个集合，获取所有与之有交流的不同用户ID
        Set<Long> conversationUserIds = new HashSet<>();
        conversationUserIds.addAll(senderIds);
        conversationUserIds.addAll(receiverIds);

        // 移除当前用户自己的ID (如果存在)
        conversationUserIds.remove(currentUserId);

        // 根据用户ID获取用户对象列表
        List<User> conversationUsers = new ArrayList<>();
        for (Long userId : conversationUserIds) {
            Optional<User> userOptional = userRepository.findById(userId); // 或 userService.getUserById(userId)
            userOptional.ifPresent(conversationUsers::add);
        }

        return conversationUsers;
    }


    public Message sendMessage(Message message) {
        return messageRepository.save(message);
    }

    public List<Message> getReceivedMessages(Long userId) {
        return messageRepository.findByReceiverId(userId);
    }

    public List<Message> getConversation(Long userId1, Long userId2) {
        return messageRepository.findBySenderIdAndReceiverId(userId1, userId2);
    }

    public Message markAsRead(Long messageId) {
        Message message = messageRepository.findById(messageId).orElse(null);
        if (message != null) {
            message.setIsRead(true);
            return messageRepository.save(message);
        }
        return null;
    }

    @Transactional
    public Message addComment(Message comment) {
        logger.info("Saving comment in service: senderId={}, receiverId={}, itemId={}, content={}",
                comment.getSenderId(), comment.getReceiverId(), comment.getItemId(), comment.getContent());
        return messageRepository.save(comment);
    }

    @Transactional
    public List<MessageDto> getCommentsByItemId(Long itemId) {
        List<Message> messages = messageRepository.findByItemIdOrderByCreatedAtAsc(itemId);
        List<MessageDto> dtos = messages.stream().map(message -> {
            MessageDto dto = new MessageDto();
            dto.setMessageId(message.getMessageId());
            dto.setSenderId(message.getSenderId());
            dto.setReceiverId(message.getReceiverId());
            dto.setItemId(message.getItemId());
            dto.setContent(message.getContent());
            dto.setIsRead(message.getIsRead());
            dto.setCreatedAt(message.getCreatedAt());

            // Fetch sender nickname
            userRepository.findById(message.getSenderId()).ifPresent(user -> {
                dto.setSenderNickname(user.getNickname());
            });
            return dto;
        }).collect(Collectors.toList());

        // Mark these comments as read after fetching
        messages.forEach(message -> {
            if (message.getIsRead() == null || !message.getIsRead()) { // Only mark unread ones
                message.setIsRead(true);
                messageRepository.save(message);
            }
        });

        return dtos;
    }

    public boolean hasUnreadCommentsForSeller(Long sellerId) {
        return messageRepository.countUnreadCommentsBySellerId(sellerId) > 0;
    }

    public boolean hasUnreadCommentsForItem(Long itemId, Long receiverId) {
        return messageRepository.countUnreadCommentsByItemIdAndReceiverId(itemId, receiverId) > 0;
    }

    @Transactional
    public void deleteComment(Long messageId, Long currentUserId) {
        Message message = messageRepository.findById(messageId)
                .orElseThrow(() -> new RuntimeException("Comment not found with id: " + messageId));

        Long commentSenderId = message.getSenderId();
        Long commentedItemId = message.getItemId();

        // Check if the comment belongs to an item (it should for a comment)
        if (commentedItemId == null) {
            throw new RuntimeException("Comment is not associated with an item.");
        }

        // Get the sellerId of the item the comment is on
        Item item = itemService.getItemById(commentedItemId);
        if (item == null) {
            throw new RuntimeException("Item associated with comment not found.");
        }
        Long itemSellerId = item.getSellerId();

        // Authorization check: only sender or item seller can delete
        if (!currentUserId.equals(commentSenderId) && !currentUserId.equals(itemSellerId)) {
            logger.warn("User {} attempted to delete comment {} but is neither the sender ({}) nor the item seller ({})",
                    currentUserId, messageId, commentSenderId, itemSellerId);
            throw new RuntimeException("You do not have permission to delete this comment.");
        }

        messageRepository.deleteById(messageId);
        logger.info("Comment {} deleted by user {}", messageId, currentUserId);
    }
}